package com.CST.service.impl.ys;

import com.CST.common.StaticVariable;
import com.CST.common.constant.Constants;
import com.CST.dto.ys.NumAndYardDTO;
import com.CST.dto.ys.YsBusinessBudgetDTO;
import com.CST.entity.cb.BdSysUser;
import com.CST.entity.ys.*;
import com.CST.mapper.cst.cb.BdSysUserMapper;
import com.CST.mapper.cst.ys.YsAccountDetailMapper;
import com.CST.mapper.cst.ys.YsAppealRecordMapper;
import com.CST.mapper.cst.ys.YsManageBudgetMapper;
import com.CST.mapper.cst.ys.YsSubjectMapper;
import com.CST.service.ys.YsComplaintService;
import com.CST.service.ys.YsManageBudgetService;
import com.CST.util.ExcelTransfer;
import com.CST.util.HttpUtil;
import com.CST.util.PageHelperTool;
import com.CST.vo.ys.*;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author chengwen
 */
@Service
public class YsManageBudgetServiceImpl extends ServiceImpl<YsManageBudgetMapper, YsAccountDetail> implements YsManageBudgetService  {
    private final ExcelTransfer<YsAccountDetailBusinessOrManageVO> excelTransfer;

    @Autowired
    private YsAccountDetailMapper ysAccountDetailMapper;

    @Autowired
    private YsComplaintService complaintService;

    @Autowired
    private BdSysUserMapper userMapper;

    @Autowired
    private YsSubjectMapper ysSubjectMapper;

    @Autowired
    private YsAppealRecordMapper ysAppealRecordMapper;

    public YsManageBudgetServiceImpl(ExcelTransfer<YsAccountDetailBusinessOrManageVO> excelTransfer) {
        this.excelTransfer = excelTransfer;
    }

    @Override
    public YsManageAccountVO getManageBudgetList(YsBusinessBudgetDTO dto) {
        YsManageAccountVO ysManageAccountVo = new YsManageAccountVO();
        List<YsAccountDetailBusinessOrManageVO> resultList = baseMapper.selectYsBudgetList(dto);
        ysManageAccountVo.setDetailList(PageHelperTool.excutePageInfo(resultList, dto.getPageNum(), dto.getPageSize()));
        List<ExpenseVO> expenseVOList = baseMapper.selectYsBudgetListCount(dto);
        BigDecimal total = expenseVOList.stream().
                map(ExpenseVO::getAMOUNT).reduce(BigDecimal.ZERO,BigDecimal::add);
        ExpenseVO evo = new ExpenseVO();
        evo.setSubjectName("总费用");
        evo.setSort(0);
        evo.setAMOUNT(total);
        expenseVOList.add(evo);
        ysManageAccountVo.setExpenseVOList(expenseVOList);
        return ysManageAccountVo;
    }

    @Override
    public Boolean insertManageBudget(YsAccountDetail ysAccountDetail) {
        Integer num = ysAccountDetailMapper.selectMaxId();
        ysAccountDetail.setNum(num+1);
        ysAccountDetail.setType(2);
        ysAccountDetail.setInsertFlag(1);
        ysAccountDetail.setDeleteFlag(0);
        ysAccountDetail.setCreateTime(LocalDateTime.now());
        ysAccountDetail.setUpdateTime(LocalDateTime.now());
        ysAccountDetail.setCreateBy(HttpUtil.getRequestHeaderInfo(Constants.USER_NAME));
        ysAccountDetail.setUpdateBy(HttpUtil.getRequestHeaderInfo(Constants.USER_NAME));
        SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd ");
        String date = formatter.format(ysAccountDetail.getDTime());
        ysAccountDetail.setPeriod(Integer.valueOf(date.replace("-","").substring(0,6)));
        ysAccountDetailMapper.insert(ysAccountDetail);
        return true;
    }

    @Override
    public YsAccountDetailBusinessOrManageVO selectInfoByNum(Integer id) {
        return baseMapper.selectInfoByNum(id);
    }

    @Override
    public Integer updateManageAccountByNum(YsAccountDetail ysAccountDetail) {
        // 首先去修订记录表中根据用友编号查询，是否存在这条数据的编辑记录
        int count = baseMapper.selectRecordIsExist(ysAccountDetail.getNum(),2);
        SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd ");
        String date = formatter.format(ysAccountDetail.getDTime());
        ysAccountDetail.setPeriod(Integer.valueOf(date.replace("-","").substring(0,6)));
        switch (count){
            case 0:
                NumAndYardDTO dto = new NumAndYardDTO();
                dto.setId(ysAccountDetail.getNum());
                dto.setYard(ysAccountDetail.getYard());
                dto.setType(ysAccountDetail.getType());
                // 查询数据，插入修订记录表YS_MODIFY_RECORDS
                YsAccountDetailBusinessOrManageVO info = baseMapper.selectInfoByNum(ysAccountDetail.getId());
                YsModifyRecords record = recordSetting("编辑",0);
                String dtime = formatter.format(info.getDateTime());
                ysAccountDetail.setPeriod(Integer.valueOf(dtime.replace("-","").substring(0,6)));
                baseMapper.insertRecord(info,record);
                // 先删除后插入
                baseMapper.deleteByNum(ysAccountDetail.getId());
                break;
            case 1:
                baseMapper.deleteByNumAndDeleteFlag(ysAccountDetail);
                break;
            default:
                break;
        }

        // 更改申诉状态-- 根据编号查询到相应到申诉数据，修改申诉状态
        BdSysUser user = userMapper.getUserById(HttpUtil.getRequestHeaderInfo(Constants.USER_ID));
//        BdSysUser user = userMapper.getUserById("283E3761-5300-43B0-9629-3C175E29D813");
        Optional.ofNullable(user).orElseThrow(()-> new RuntimeException("用户未登录"));
        YsAppealRecord record = new YsAppealRecord();
        record.setNum(ysAccountDetail.getNum());
        record.setStatus(2);
        record.setHandleTime(LocalDateTime.now());
        record.setHandler(user.getId());
        ysAppealRecordMapper.updateByNum(record);

        // 来源 1业务职能，2管理职能-费用类，3管理职能资本类。4管理职能业务配套指标
        YsSubject ysSubject = ysSubjectMapper.selectById(ysAccountDetail.getSubjectId());
        Optional.ofNullable(ysSubject).orElseThrow(()-> new RuntimeException("预算科目不存在"));
        complaintService.saveEntity(YsComplaint.builder()
                .recipient(StaticVariable.LOG_YS_COMPLAINT_RECIPIENT_1)
                .source(StaticVariable.LOG_YS_COMPLAINT_SOURCE_1)
                .operate(StaticVariable.LOG_YS_COMPLAINT_OPERATE_2)
                .acceptContent(StaticVariable.LOG_YS_COMPLAINT_CONTEXT_HEAD_2
                        + ysSubject.getSubjectName() +"("
                        + ysSubject.getSubjectCode() + ")"
                        + StaticVariable.LOG_YS_COMPLAINT_CONTEXT_2)
                .jumpPage(StaticVariable.LOG_YS_COMPLAINT_PAGE_1)
                .complaintUser(user.getUserName())
                .build());

        ysAccountDetail.setInsertFlag(2);
        ysAccountDetail.setDeleteFlag(0);
        ysAccountDetail.setType(2);
        ysAccountDetail.setCreateTime(LocalDateTime.now());
        ysAccountDetail.setCreateBy(HttpUtil.getRequestHeaderInfo(Constants.USER_NAME));
        ysAccountDetail.setUpdateBy(HttpUtil.getRequestHeaderInfo(Constants.USER_NAME));
        ysAccountDetail.setUpdateTime(LocalDateTime.now());
        return  baseMapper.insert(ysAccountDetail);
    }

    @Override
    public Boolean deleteByNum(Integer id) {
        // 查询数据，插入修订记录表YS_MODIFY_RECORDS
        YsAccountDetailBusinessOrManageVO info = baseMapper.selectInfoByNum(id);
        if (info == null){
            return true;
        }
        YsModifyRecords record = recordSetting("删除",1);
        baseMapper.insertRecord(info,record);
        baseMapper.deleteByNum(id);
        return true;
    }

    @Override
    public Boolean releaseData(YsBusinessBudgetDTO dto) {
        try {
            List<YsAccountDetailBusinessOrManageVO> resultList = baseMapper.selectYsBudgetList(dto);
            // 分批插入YS_ACCOUNT_DETAIL_RE
            // 先根据条件删除数据
            baseMapper.deleteByDto(dto);
            int total = resultList.size();
            if (total > 0) {
                int fromIndex = 0;
                List<YsAccountDetailBusinessOrManageVO> insertList = new ArrayList<>();
                for (YsAccountDetailBusinessOrManageVO item : resultList) {
                    fromIndex++;
                    insertList.add(item);
                    if (fromIndex % 50 == 0 && fromIndex <= total) {
                        baseMapper.insertYsAccountDetailRe(insertList);
                        insertList = new ArrayList<>();
                    }
                }
                if (CollectionUtils.isNotEmpty(insertList)) {
                    baseMapper.insertYsAccountDetailRe(insertList);
                }
            }
        } catch (RuntimeException e){
            throw new RuntimeException("发布失败");
        }
        return true;
    }

    @Override
    public PageInfo<YsModifyRecordVO> getModifyRecordList(YsBusinessBudgetDTO ysBusinessBudgetDto) {
        List<YsModifyRecordVO> recordList = baseMapper.selectModifyRecordList(ysBusinessBudgetDto);
        return PageHelperTool.excutePageInfo(recordList, ysBusinessBudgetDto.getPageNum(), ysBusinessBudgetDto.getPageSize());
    }

    @Override
    public Boolean revokeRecord(NumAndYardDTO dto) {
        // 根据id查询num数据是否存在
        int count = baseMapper.selectRecordById(dto);
        if (count > 0){
            throw new RuntimeException("管理执行列表存在重复数据，请删除相同数据再执行撤销操作");
        }
        // 根据id查询数据，根据num将detail表中的数据还原
        baseMapper.updateDetailDeleteFlagById(dto);
        // 逻辑删除修订记录表数据
        baseMapper.DeleteRecordById(dto.getId());
        return true;
    }

    @Override
    public void exportExcelYsManageBudget(HttpServletResponse response, YsBusinessBudgetDTO dto) {
        excelTransfer.exportExcel(response, baseMapper.selectYsBudgetList(dto), "管理费用类预算执行管理", "sheet",
                YsAccountDetailBusinessOrManageVO.class);
    }

    private YsModifyRecords recordSetting(String content, Integer flag) {
        YsModifyRecords record = new YsModifyRecords();
        record.setOperContent(content);
        record.setOperPerson(HttpUtil.getRequestHeaderInfo(Constants.USER_NAME));
        record.setOperTime(LocalDateTime.now());
        record.setRevokeFlag(flag);
        record.setType(2);
        return record;
    }
}
